<?php

declare(strict_types=1);

namespace App\Model\PssModel;

use App\Model\BaseModel\BasePssModel;
use App\Service\Code\Normal;
use App\Service\OrderService\OrderQueryService\QueryGoodsMicService;
use Hyperf\DbConnection\Db;

class ShopSeckill extends BasePssModel
{
    public $table = 'shop_seckill';
    const CUT_DOWN_GOODS_LIMIT  = 4;
    const SECKILL_STATUS = 0;
    
    /**
     * 获取秒杀信息
     * @param $sec_id
     */
    public function getSeckillInfoBySecId( $sec_id = '' )
    {
        return $this->info(['id'=>$sec_id]);
    }
    
    /**
     * 获取距离活动开始满足时间间距最近的一场秒杀活动数据配置 
     * @param array $param
     */
    public function getGoodsSeckillIndexInfo( $param = [] )
    {
        $countDownSecMis = $this->getSecKillSortList(true);
        //获取当前秒杀场次的前几个商品
        $secKillGoodsList = [];
        if( !empty($countDownSecMis) ) {
            $sec_id = $countDownSecMis['sec_id'];
            $secKillGoodsList = ShopSeckillGoodsList::instance()
            ->select($this->getSecKillQueryColumns())
            ->where('seckill_id',$countDownSecMis['sec_id'])
            ->limit(self::CUT_DOWN_GOODS_LIMIT)
            ->get()
            ->toArray();
            if( !empty($secKillGoodsList) ) {
                foreach ($secKillGoodsList as & $item ) {
                    $item['storeList']  = @json_decode($item['storeList'],true);
                    $item['images']     = @json_decode($item['images'],true);
                }
                $res = QueryGoodsMicService::instance()->getGoodsListByCaculationAction($param['binfo'],$secKillGoodsList,[],$sec_id);
                $secKillGoodsList = $res['data'];
            }
        }
        
        $getHomeShowConfigData          = ShopHomeShow::instance()->getHomeShowConfigDataByShowType([ShopHomeShow::SECKILL]);
        $current                        = current($getHomeShowConfigData);
        $countDownSecMis['dataList']    = $secKillGoodsList;
        $countDownSecMis['sort']        = $current['sort']??0;
        return Normal::returnCode(Normal::SUC,"获取成功",$countDownSecMis);
    }
    
    /**
     * 获取查询秒杀数据模型
     */
    public function getSecKillQuery() 
    {
        return $this
        ->where('seckill_status',self::SECKILL_STATUS)//活动开启状态
        ->where('end_date','>=',date("Ymd"))
        ->where('end_date','>=',Db::raw('start_date'))
        ->where('sale_end_time','>',Db::raw('sale_start_time'))
        ->orderby('start_date','asc')
        ->orderby('sale_start_time','asc');
    }
    
    /**
     * 获取查询秒杀数据字段
     */
    public function getSecKillQueryColumns() 
    {
        return [
            Db::raw("intro_name as introName"),
            Db::raw("description as description"),
            Db::raw("goods_name as goodsName"),
            Db::raw("brand_name as brandName"),
            Db::raw("goods_type as goodsType"),
            Db::raw("goods_type_name as goodsTypeName"),
            Db::raw("sclass_id as categoryPid"),
            Db::raw("commodity_label as commodityLabel"),
            Db::raw("barcode"),
            Db::raw("skucode"),
            Db::raw("has_rate as isHaveTaxRate"),
            Db::raw("tax_rate as tax_rate"),
            Db::raw("tax_rate as taxRate"),
            'weight',
            'images',
            Db::raw("CONCAT('',goods_id) as goods_id"),
            Db::raw("CONCAT('',goods_id) as SkuID"),
            Db::raw("spec_list as storeList")
        ];
    }
    
    /**
     * 是否获取全部数据
     * @param boolean $isOpenSeckillStatus 是否开启预告 (true -开启，false -不开启) 
     */
    public function getSecKillSortList( $isOpenSeckillStatus = false )
    {
        //计算日期
        $now                = time();
        //当日0点
        $now_date           = date("Ymd");
        //当日0点时间戳
        $now_start_time     = strtotime($now_date);
        //当日实时开始已用秒数
        $now_date_mics      = $now - $now_start_time;
        $one_days_time      = 86400;
        $secKillList        = $this->getSecKillQuery()->get()->toArray();
        $countDownSecPreMis = [];
        foreach ($secKillList as $item )
        {
            $start_date         = $item['start_date'];
            $end_date           = $item['end_date'];
            $sale_start_time    = $item['sale_start_time'];
            $sale_end_time      = $item['sale_end_time'];
            $seckill_id         = (string)$item['id'];
            $seckill_name       = $item['seckill_name'];
            $status             = $item['status'];
        
            //日期间隔多少天
            $n_days = ($end_date - $start_date) / $one_days_time;
            for( $i = 0 ; $i <= $n_days ; $i ++ )
            {
                //预计开始秒杀时间
                $start_time = $start_date + $i * $one_days_time + $sale_start_time;
                //预计秒杀结束时间
                $end_time   = $start_date + $i * $one_days_time + $sale_end_time;
                if( $end_time >= $now ) {//每一场次结束时间大于当前时间
                    if( $start_time < $now_start_time ) { //48小时的数据
                        $countDownSecPreMis[] = [
                            'type'          => 'pre_start',
                            'type_name'     => '即将开始',
                            'start_time'    => $start_time,
                            'status'        => $status,
                            'start_date'    => date('Y-m-d H:i:s',$start_time),
                            'cut_time'      => $start_time - $now ,
                            'start_dt'      => date('m-d H:i',$start_time),
                            'sec_id'        => $seckill_id,
                            'seckill_name'  => $seckill_name
                        ];
                    } else {
                        //如果是过了日期未开始
                        if( $now < $start_time ) {
                            $format_start_dt = $start_date + $i * $one_days_time > 0 ? 'm-d H:i':'H:i';
                            $countDownSecPreMis[] = [
                                'type'          => 'pre_start',
                                'type_name'     => '即将开始',
                                'status'        => $status,
                                'start_time'    => $start_time,
                                'start_date'    => date('Y-m-d H:i:s',$start_time),
                                'cut_time'      => $start_time - $now,
                                'start_dt'      => date($format_start_dt,$start_time),
                                'sec_id'        => $seckill_id,
                                'seckill_name'  => $seckill_name
                            ];
                        } else {
                            $countDownSecPreMis[] = [
                                'type'          => 'start',
                                'type_name'     => '正在秒杀',
                                'start_time'    => $start_time,
                                'status'        => $status,
                                'start_date'    => date('Y-m-d H:i:s',$start_time),
                                'cut_time'      => $sale_end_time - $now_date_mics,
                                'start_dt'      => date('H:i',$start_time),
                                'sec_id'        => $seckill_id,
                                'seckill_name'  => $seckill_name
                            ];
                        }
                    }
                }
            }
        }
        
        //进行活动数据场次数据排序
        $cut_times = array_column($countDownSecPreMis, 'start_time');
        array_multisort($cut_times,SORT_ASC,$countDownSecPreMis);
        
        //首页控制是否显示预告秒杀活动数据
        if( $isOpenSeckillStatus && !empty($countDownSecPreMis) ) {
            $firstCountDownSecPreMis = current($countDownSecPreMis);
            
            //正在秒杀的活动
            if( $firstCountDownSecPreMis['type'] == 'start' ) {
                return $firstCountDownSecPreMis;
            }
            
            //只展示首页开启预告的情况
            return $firstCountDownSecPreMis['status'] == 1 && $firstCountDownSecPreMis['start_time'] - $now < 86400 * 2 ? $firstCountDownSecPreMis : [] ;
        }
        
        return $countDownSecPreMis;
    }
    
    /**
     * 获取秒杀活动列表
     * @param array $param
     */
    public function getSeckillList( $param = [] )
    {
        return Normal::returnCode(Normal::SUC,"获取成功",[
            'secKillList' => $this->getSecKillSortList()
        ]);
    }
    
    /**
     * 获取当前秒杀活动对应的商品
     * @param array $param
     */
    public function getSeckillGoodsListBySeckillId( $param = [] )
    {
        $body   = $param['body'];
        $binfo  = $param['binfo'];
        $page   = isset($body['page']) ? $body['page'] : 1 ;
        $limit  = isset($body['limit']) ? $body['limit'] : 10 ;
        
        if( empty($body['sec_id']) ) {
            return Normal::returnCode(Normal::FAIL,"except param sec_id");
        }
        
        //计算日期
        $now                = time();
        //当日0点
        $now_date           = date("Ymd");
        //当日0点时间戳
        $now_start_time     = strtotime($now_date);
        //当日实时开始已用秒数
        $now_date_mics      = $now - $now_start_time;
        
        $sec_id = $body['sec_id'];
        $info = $this->where('id',$sec_id)
        ->where('seckill_status',self::SECKILL_STATUS)
        ->where('end_date','>=',date("Ymd"))
        ->where('end_date','>=',Db::raw('start_date'))
        //->where('sale_end_time','>',Db::raw('sale_start_time'))
        //->where('sale_end_time','>=',$now_date_mics)
        ->get()
        ->toArray();
        if( empty($info) ) {
            return Normal::returnCode(Normal::FAIL,"未找到满足条件的数据");
        }
        
        $columns = $this->getSecKillQueryColumns();
        $list = ShopSeckillGoodsList::instance()->where('seckill_id',$sec_id)->paginate($limit, $columns, 'page', $page)->toArray();
        if( !empty($list['data']) ) {
            foreach ($list['data'] as & $item ) {
                $item['storeList']  = @json_decode($item['storeList'],true);
                $item['images']     = @json_decode($item['images'],true);
            }
            $res = QueryGoodsMicService::instance()->getGoodsListByCaculationAction($binfo,$list['data'],[],$sec_id);
            $list['data'] = $res['data'];
        }
        return Normal::returnCode(Normal::SUC,"获取成功",$list);
    }
    
    /**
     * 通过SKUIDs集合查询 当前商品是否有参与秒杀
     * @param array $skuId
     * @param string $sec_id
     */
    public function querySecSkillGoodsInfoBySkuIds( array $skuIds ,$sec_id = false )
    {
        //计算日期
        $now                = time();
        //当日0点
        $now_date           = date("Ymd");
        //当日0点时间戳
        $now_start_time     = strtotime($now_date);
        //当日实时开始已用秒数
        $now_date_mics      = $now - $now_start_time;
        
        //查询数据
        $query = ShopSeckillGoodsList::instance()
        ->select([
            'shop_seckill_goods_list.goods_id',
            'shop_seckill_goods_list.spec_list',
            'ss.*'
        ])
        ->join('shop_seckill as ss', 'shop_seckill_goods_list.seckill_id', '=', 'ss.id')
        ->whereIn('shop_seckill_goods_list.goods_id',$skuIds)
        ->where('ss.seckill_status',self::SECKILL_STATUS)
        ->where('ss.end_date','>=',$now_start_time);
        
        //如果秒杀商品列表
        if( $sec_id ) {
            $query->where('ss.id',$sec_id);
        } else {
            $query->where('ss.sale_end_time','>=',$now_date_mics)
            ->where('ss.start_date','<=',$now_start_time)
            ->where('ss.sale_start_time','<=',$now_date_mics);
        }
        
        $list = $query->get()->toArray();
        $newSeckillGoodsListMap = [];
        foreach ($list as $key => & $info ) 
        {
            $storeList = @json_decode($info['spec_list'],true);
            if( empty($storeList) ) {
                unset($list[$key]);
                continue;
            }
            
            $storeListMap = array_column($storeList, null,'store_id');
            foreach ($storeListMap as & $item ) {
                $item['goods_batch_list'] = array_column($item['goods_batch_list'], null,'batch_no');
                foreach ($item['goods_batch_list'] as & $batch ) {
                    $batch['spec_list'] = array_column($batch['spec_list'], null,'spec_num');
                }
            }
            $info['spec_list'] = $storeListMap;
        }
        
        $seckill_info = current($list);
        unset($seckill_info['spec_list'],$seckill_info['goods_id']);
        if( !empty($seckill_info) ) {
            $seckill_info['now_start_time'] = $now_start_time;
            $seckill_info['now_date_mics']  = $now_date_mics;
        }
        return [
            'secGoodsList'  => array_column($list,null,'goods_id'),
            'seckill_info'  => $seckill_info,
        ];
    }
    
    /**
     * 获取秒杀是否有效
     * @param array $seckillInfo
     */
    public function getSeckillGoodsActivity( $seckillInfo = [] )
    {
        $now_start_time     = $seckillInfo['now_start_time'];
        $now_date_mics      = $seckillInfo['now_date_mics'];
        $start_date         = $seckillInfo['start_date'];
        $sale_start_time    = $seckillInfo['sale_start_time'];
        $sale_end_time      = $seckillInfo['sale_end_time'];
        
        if( $start_date >= $now_start_time &&  $now_date_mics >= $sale_start_time && $now_date_mics <= $sale_end_time ) {
            return true;
        }
        
        return false;
    }
}
